#pragma once
#include <iostream>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>
#include <stdexcept>

class MMAP {
private:
    void* ptr;
    int fd;
    size_t size;

public:
    MMAP(const char* filePath, size_t create_size, bool write) {
        fd = -1;
        ptr = nullptr;
        if (create_size > 0) write = true;
        int flags = O_RDWR; 
        if (!write) {
            flags = O_RDONLY; 
        }

        if (create_size > 0) {
            fd = open(filePath, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
            if (fd == -1) {
                throw std::runtime_error("Failed to open file for writing");
            }

            if (ftruncate(fd, create_size) == -1) {
                close(fd);
                throw std::runtime_error("Failed to set file size");
            }

            size = create_size;
        }
        else {
            fd = open(filePath, flags);
            if (fd == -1) {
                throw std::runtime_error("Failed to open file");
            }

            struct stat sb;
            if (fstat(fd, &sb) == -1) {
                close(fd);
                throw std::runtime_error("Failed to get file size");
            }

            size = sb.st_size;
        }

        ptr = mmap(0, size, PROT_READ | (write ? PROT_WRITE : 0), MAP_SHARED, fd, 0);
        if (ptr == MAP_FAILED) {
            close(fd);
            throw std::runtime_error("Failed to map file to memory");
        }
    }

    ~MMAP() {
        if (ptr != nullptr) {
            munmap(ptr, size);
        }
        if (fd != -1) {
            close(fd);
        }
    }

    void* getPtr() {
        return ptr;
    }
    size_t getSize() {
        return size;
    }
};

